package org.filetransfer.file_transfer_java_backend.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.filetransfer.file_transfer_java_backend.entity.User;
import org.filetransfer.file_transfer_java_backend.repository.UserRepository;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
import java.util.UUID;

@Service
@RequiredArgsConstructor
@Slf4j
@Transactional
public class AvatarService {
    
    private final UserRepository userRepository;
    
    @Value("${file.upload.dir}")
    private String fileStorageDir;
    
    // 支持的图片格式
    private static final List<String> SUPPORTED_IMAGE_TYPES = Arrays.asList(
        "image/jpeg", "image/jpg", "image/png", "image/gif", "image/webp", "image/bmp"
    );
    
    // 头像尺寸配置
    private static final int AVATAR_SIZE = 200; // 标准头像大小
    private static final int THUMBNAIL_SIZE = 50; // 缩略图大小
    private static final int MAX_FILE_SIZE = 5 * 1024 * 1024; // 5MB
      /**
     * 上传用户头像
     */
    public String uploadAvatar(Long userId, byte[] imageData, String fileName, String contentType) throws IOException {
        // 验证文件
        validateImageFile(imageData, fileName, contentType);
        
        // 获取用户
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
        
        // 创建头像存储目录
        String avatarDir = getAvatarDirectory();
        ensureDirectoryExists(avatarDir);
        
        // 生成唯一文件名
        String fileExtension = getFileExtension(fileName);
        String newFileName = "avatar_" + userId + "_" + UUID.randomUUID().toString() + "." + fileExtension;
          // 处理并保存图片
        saveProcessedAvatar(imageData, avatarDir, newFileName);
        
        // 删除旧头像文件
        deleteOldAvatar(user.getAvatarUrl());
        
        // 生成访问URL
        String avatarUrl = "/api/avatar/" + newFileName;
        
        // 更新用户头像URL
        user.setAvatarUrl(avatarUrl);
        userRepository.save(user);
        
        log.info("用户 {} 头像上传成功: {}", userId, avatarUrl);
        return avatarUrl;
    }
    
    /**
     * 获取头像文件
     */
    public File getAvatarFile(String fileName) throws IOException {
        String avatarDir = getAvatarDirectory();
        Path filePath = Paths.get(avatarDir, fileName);
        
        File file = filePath.toFile();
        if (!file.exists()) {
            throw new IOException("头像文件不存在: " + fileName);
        }
        
        return file;
    }
    
    /**
     * 获取头像缩略图
     */
    public File getAvatarThumbnail(String fileName) throws IOException {
        String avatarDir = getAvatarDirectory();
        String thumbnailFileName = "thumb_" + fileName;
        Path thumbnailPath = Paths.get(avatarDir, "thumbnails", thumbnailFileName);
        
        File thumbnailFile = thumbnailPath.toFile();
        
        // 如果缩略图不存在，生成一个
        if (!thumbnailFile.exists()) {
            File originalFile = getAvatarFile(fileName);
            generateThumbnail(originalFile, thumbnailFile);
        }
        
        return thumbnailFile;
    }
    
    /**
     * 删除用户头像
     */
    public void deleteAvatar(Long userId) {
        User user = userRepository.findById(userId)
            .orElseThrow(() -> new IllegalArgumentException("用户不存在"));
        
        deleteOldAvatar(user.getAvatarUrl());
        
        user.setAvatarUrl(null);
        userRepository.save(user);
        
        log.info("用户 {} 头像删除成功", userId);
    }    /**
     * 验证图片文件
     */
    private void validateImageFile(byte[] imageData, String fileName, String contentType) {
        if (imageData == null || imageData.length == 0) {
            throw new IllegalArgumentException("图片数据不能为空");
        }
        
        if (imageData.length > MAX_FILE_SIZE) {
            throw new IllegalArgumentException("文件大小不能超过5MB");
        }
        
        if (contentType == null || !SUPPORTED_IMAGE_TYPES.contains(contentType.toLowerCase())) {
            throw new IllegalArgumentException("不支持的图片格式，支持：JPG、PNG、GIF、WEBP、BMP");
        }
        
        // 验证文件头，确保文件内容与声明的类型一致
        String detectedFormat = detectImageFormat(imageData);
        log.debug("文件 {} 声明类型: {}, 检测到的格式: {}", fileName, contentType, detectedFormat);
        
        // 检查文件头是否匹配声明的MIME类型
        if (!isFormatMatchingContentType(detectedFormat, contentType)) {
            log.warn("文件格式不匹配: 声明为 {} 但检测到 {}", contentType, detectedFormat);
            // 不抛出异常，允许通过，但记录警告
        }
    }
    
    /**
     * 检查检测到的格式是否与Content-Type匹配
     */
    private boolean isFormatMatchingContentType(String detectedFormat, String contentType) {
        if (detectedFormat.startsWith("未知")) {
            return false;
        }
        
        contentType = contentType.toLowerCase();
        detectedFormat = detectedFormat.toLowerCase();
        
        return (contentType.contains("jpeg") || contentType.contains("jpg")) && detectedFormat.equals("jpeg") ||
               contentType.contains("png") && detectedFormat.equals("png") ||
               contentType.contains("gif") && detectedFormat.equals("gif") ||
               contentType.contains("webp") && detectedFormat.equals("webp") ||
               contentType.contains("bmp") && detectedFormat.equals("bmp");
    }    /**
     * 处理并保存头像
     */
    private String saveProcessedAvatar(byte[] imageData, String avatarDir, String fileName) throws IOException {
        Path avatarPath = Paths.get(avatarDir, fileName);
        
        try {
            // 验证图片数据
            if (imageData == null || imageData.length == 0) {
                throw new IOException("图片数据为空");
            }
            
            log.debug("开始处理图片，数据大小: {} bytes", imageData.length);
            
            // 检查是否是Base64编码的数据
            byte[] actualImageData = decodeIfBase64(imageData);
            log.debug("解码后图片数据大小: {} bytes", actualImageData.length);              // 从字节数组读取原始图片
            ByteArrayInputStream inputStream = new ByteArrayInputStream(actualImageData);
            BufferedImage originalImage = null;
            
            try {
                originalImage = ImageIO.read(inputStream);
            } catch (Exception e) {
                log.error("ImageIO读取图片失败: {}", e.getMessage());
                
                // 尝试使用不同的方法读取
                try {
                    inputStream = new ByteArrayInputStream(actualImageData); // 重新创建输入流
                    originalImage = readImageWithFallback(inputStream);
                } catch (Exception fallbackException) {
                    log.error("备用方法也无法读取图片: {}", fallbackException.getMessage());
                    throw new IOException("图片格式错误或数据损坏: " + e.getMessage() + ", 备用方法: " + fallbackException.getMessage());
                }
            }
            
            if (originalImage == null) {
                // 尝试检测图片格式
                String detectedFormat = detectImageFormat(actualImageData);
                log.error("ImageIO无法解析图片，检测到的格式: {}, 文件名: {}", detectedFormat, fileName);
                
                // 尝试保存原始文件进行调试
                try {
                    Path debugPath = Paths.get(avatarDir, "debug_" + fileName);
                    Files.write(debugPath, actualImageData);
                    log.debug("原始文件已保存到: {} 用于调试", debugPath);
                } catch (Exception debugException) {
                    log.warn("无法保存调试文件: {}", debugException.getMessage());
                }
                
                throw new IOException("无法读取图片文件，可能是不支持的格式或数据损坏。检测到的格式: " + detectedFormat);
            }
            
            log.debug("成功读取图片，尺寸: {}x{}", originalImage.getWidth(), originalImage.getHeight());
            
            // 调整图片大小并保存
            Thumbnails.of(originalImage)
                .size(AVATAR_SIZE, AVATAR_SIZE)
                .keepAspectRatio(true)
                .crop(net.coobird.thumbnailator.geometry.Positions.CENTER)
                .outputQuality(0.9)
                .toFile(avatarPath.toFile());
            
            // 生成缩略图
            generateThumbnail(avatarPath.toFile(), new File(avatarDir + "/thumbnails/thumb_" + fileName));
            
            return avatarPath.toString();
            
        } catch (Exception e) {
            log.error("处理头像图片失败", e);
            throw new IOException("图片处理失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成缩略图
     */
    private void generateThumbnail(File originalFile, File thumbnailFile) throws IOException {
        // 确保缩略图目录存在
        ensureDirectoryExists(thumbnailFile.getParent());
        
        Thumbnails.of(originalFile)
            .size(THUMBNAIL_SIZE, THUMBNAIL_SIZE)
            .keepAspectRatio(true)
            .crop(net.coobird.thumbnailator.geometry.Positions.CENTER)
            .outputQuality(0.8)
            .toFile(thumbnailFile);
    }
    
    /**
     * 删除旧头像文件
     */
    private void deleteOldAvatar(String oldAvatarUrl) {
        if (oldAvatarUrl == null || oldAvatarUrl.isEmpty()) {
            return;
        }
        
        try {
            // 从URL中提取文件名
            String fileName = oldAvatarUrl.substring(oldAvatarUrl.lastIndexOf("/") + 1);
            String avatarDir = getAvatarDirectory();
            
            // 删除主文件
            Path avatarPath = Paths.get(avatarDir, fileName);
            Files.deleteIfExists(avatarPath);
            
            // 删除缩略图
            Path thumbnailPath = Paths.get(avatarDir, "thumbnails", "thumb_" + fileName);
            Files.deleteIfExists(thumbnailPath);
            
            log.debug("删除旧头像文件: {}", fileName);
        } catch (Exception e) {
            log.warn("删除旧头像文件失败: {}", e.getMessage());
        }
    }
    
    /**
     * 获取头像存储目录
     */
    private String getAvatarDirectory() {
        return fileStorageDir + "/avatars";
    }
    
    /**
     * 确保目录存在
     */
    private void ensureDirectoryExists(String directory) throws IOException {
        Path path = Paths.get(directory);
        if (!Files.exists(path)) {
            Files.createDirectories(path);
        }
    }
    
    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        if (fileName == null || !fileName.contains(".")) {
            return "jpg";
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
    }
    
    /**
     * 检测图片格式
     */
    private String detectImageFormat(byte[] imageData) {
        if (imageData == null || imageData.length < 4) {
            return "未知格式";
        }
        
        // 检查文件头
        if (imageData.length >= 3 && 
            imageData[0] == (byte) 0xFF && 
            imageData[1] == (byte) 0xD8 && 
            imageData[2] == (byte) 0xFF) {
            return "JPEG";
        }
        
        if (imageData.length >= 8 && 
            imageData[0] == (byte) 0x89 && 
            imageData[1] == 0x50 && 
            imageData[2] == 0x4E && 
            imageData[3] == 0x47 && 
            imageData[4] == 0x0D && 
            imageData[5] == 0x0A && 
            imageData[6] == 0x1A && 
            imageData[7] == 0x0A) {
            return "PNG";
        }
        
        if (imageData.length >= 6 && 
            imageData[0] == 0x47 && 
            imageData[1] == 0x49 && 
            imageData[2] == 0x46 && 
            imageData[3] == 0x38 && 
            (imageData[4] == 0x37 || imageData[4] == 0x39) && 
            imageData[5] == 0x61) {
            return "GIF";
        }
        
        if (imageData.length >= 12 && 
            imageData[0] == 0x52 && 
            imageData[1] == 0x49 && 
            imageData[2] == 0x46 && 
            imageData[3] == 0x46 && 
            imageData[8] == 0x57 && 
            imageData[9] == 0x45 && 
            imageData[10] == 0x42 && 
            imageData[11] == 0x50) {
            return "WEBP";
        }
        
        if (imageData.length >= 2 && 
            imageData[0] == 0x42 && 
            imageData[1] == 0x4D) {
            return "BMP";
        }
        
        return "未知格式 (前4字节: " + 
               String.format("%02X %02X %02X %02X", 
                           imageData[0] & 0xFF, 
                           imageData[1] & 0xFF, 
                           imageData[2] & 0xFF, 
                           imageData[3] & 0xFF) + ")";
    }
      /**
     * 备用图片读取方法
     */
    private BufferedImage readImageWithFallback(ByteArrayInputStream inputStream) throws IOException {
        // 重置输入流
        inputStream.reset();
        
        // 获取所有可用的图片读取器
        var readers = ImageIO.getImageReaders(inputStream);
        
        if (!readers.hasNext()) {
            throw new IOException("没有找到合适的图片读取器");
        }
        
        while (readers.hasNext()) {
            var reader = readers.next();
            try {
                // 重置输入流
                inputStream.reset();
                reader.setInput(inputStream, true, true);
                BufferedImage image = reader.read(0);
                if (image != null) {
                    return image;
                }
            } catch (Exception e) {
                log.debug("图片读取器 {} 失败: {}", reader.getClass().getSimpleName(), e.getMessage());
            } finally {
                reader.dispose();
            }
        }
        
        throw new IOException("所有图片读取器都无法处理此文件");
    }
    
    /**
     * 如果数据是Base64编码，则解码；否则返回原数据
     */
    private byte[] decodeIfBase64(byte[] data) {
        try {
            // 检查是否看起来像Base64数据
            String dataStr = new String(data, "UTF-8");
            
            // 移除可能的data URL前缀 (如: data:image/jpeg;base64,)
            if (dataStr.startsWith("data:")) {
                int commaIndex = dataStr.indexOf(',');
                if (commaIndex != -1) {
                    dataStr = dataStr.substring(commaIndex + 1);
                }
            }
            
            // 检查是否是有效的Base64字符串
            if (isValidBase64(dataStr)) {
                log.debug("检测到Base64编码数据，正在解码...");
                byte[] decoded = Base64.getDecoder().decode(dataStr);
                log.debug("Base64解码成功，原始大小: {} bytes, 解码后大小: {} bytes", data.length, decoded.length);
                return decoded;
            }
        } catch (Exception e) {
            log.debug("Base64解码失败，使用原始数据: {}", e.getMessage());
        }
        
        return data;
    }
    
    /**
     * 检查字符串是否是有效的Base64编码
     */
    private boolean isValidBase64(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        
        // 移除空白字符
        str = str.replaceAll("\\s", "");
        
        // Base64字符串长度必须是4的倍数
        if (str.length() % 4 != 0) {
            return false;
        }
        
        // 检查字符是否都是有效的Base64字符
        return str.matches("^[A-Za-z0-9+/]*={0,2}$");
    }
}
